home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / WINPROGS / DRDOBBS.ZIP / HELPDUMP.C < prev    next >
Text File  |  1993-08-02  |  41KB  |  1,233 lines

  1. /***************************************************
  2.   HLPDUMP1.C
  3.   Peter Davis - 05/93
  4.  
  5.   Taken from the original HELPDUMP.C written by
  6. Ron Burk.
  7.  
  8.   Dumps known files from WinHelp internal file
  9. system in a formatted output. If WHIFS file is
  10. unknown, hex/ascii dump of file is taken.
  11.  
  12.   HELPDUMP.C will replace HLPDUMP1.C with extended
  13. functionality for handling more WHIFS files.
  14.  
  15. ****************************************************/
  16.  
  17.  
  18. /*************************************************
  19.    If it's not Turbo C, assume MSC 6.0 As for the
  20.    rest of you, you'll have to customize. Sorry.
  21. **************************************************/
  22.  
  23. #pragma pack(1)   /* Make sure we get byte alignment */
  24.  
  25. #ifndef __TURBOC__
  26.   #include <graph.h>
  27.   #define clrscr() _clearscreen(_GCLEARSCREEN);
  28. #endif
  29.  
  30. #include <time.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <conio.h>
  35. #include <ctype.h>
  36. #include <limits.h>
  37. #include "whstruct.h"
  38. #include "helpdump.h"
  39.  
  40. HELPHEADER        HelpHeader;             /* Header for Help file.         */
  41. WHIFSBTREEHEADER  WHIFSHeader;            /* WHIFS Header record           */
  42. int               WHIFSLeafOne = -1;      /* First WHIFS Leaf Node         */
  43. long              FirstPageLoc;           /* Used by macros for b-trees    */
  44. char              WHIFSFileToRead[19];    /* Internal file to dump         */
  45. int               ReadWHIFSFile;          /* Flag to dump an internal file */
  46. SYSTEMHEADER      SysHeader;              /* Global System Header Record   */
  47. char              *PhrasesPtr; 
  48. int               TopicUse;
  49.  
  50.  
  51. /***************************************************
  52.   Finds the first leaf in the WHIFS B-Tree
  53. ****************************************************/
  54. void WHIFSGetFirstLeaf(FILE *HelpFile) {
  55.     
  56.     int               CurrLevel = 1;  /* Current Level in B-Tree */
  57.     BTREEINDEXHEADER  CurrNode;       /* Current Node in B-Tree  */
  58.     int               NextPage = 0;   /* Next Page to go to      */
  59.  
  60.     /* Go to the beginning of WHIFS B-Tree */
  61.     fseek(HelpFile, HelpHeader.WHIFS, SEEK_SET);
  62.     fread(&WHIFSHeader, sizeof(WHIFSHeader), 1, HelpFile);
  63.  
  64.     FirstPageLoc = HelpHeader.WHIFS + sizeof(WHIFSHeader);
  65.  
  66.     /* Find First Leaf */
  67.     while (CurrLevel < WHIFSHeader.NLevels) {
  68.        fread(&CurrNode, sizeof(CurrNode), 1, HelpFile);
  69.  
  70.        /* Next Page is conveniently the first byte of the page */
  71.        fread(&NextPage, sizeof(int), 1, HelpFile);
  72.        GotoWHIFSPage(NextPage);
  73.        CurrLevel++;
  74.     }
  75.  
  76.     /* First Leaf page is here */
  77.     WHIFSLeafOne = NextPage;
  78. }
  79.        
  80.     
  81.  
  82.  
  83.  
  84. /***************************************************
  85.   Gets a particular file by file number.
  86.   Needs the root node of the tree.
  87.   Returns the offset of the file and the filename.
  88. ****************************************************/
  89.  
  90. void GetFile(FILE *HelpFile, int FileNumber, long *FileOffset, char *FileName) {
  91.  
  92.     BTREENODEHEADER CurrentNode;      
  93.     int             CurrPage;              /* Keep track of page # */
  94.     int             Index, counter = 0;
  95.     char            c, TempFile[19];
  96.  
  97.     
  98.     /* Skip pages we don't need */
  99.     CurrentNode.NextPage = WHIFSLeafOne;
  100.     do {
  101.         CurrPage = CurrentNode.NextPage;
  102.         GotoWHIFSPage(CurrPage);
  103.         fread(&CurrentNode, sizeof(CurrentNode), 1, HelpFile);
  104.         counter += CurrentNode.NEntries;
  105.     } while (counter < FileNumber);
  106.  
  107.     for (counter -= CurrentNode.NEntries; counter <= FileNumber; counter++) {
  108.         Index = 0;
  109.     while(c = fgetc(HelpFile))
  110.             TempFile[Index++] = c;
  111.          
  112.         TempFile[Index] = 0;  /* End of line */
  113.         fread(FileOffset, sizeof(long), 1, HelpFile);
  114.     }
  115.     strcpy(FileName, TempFile);
  116.  
  117. }
  118.  
  119.  
  120. /***************************************************
  121.   Loads the SysHeader into memory. Need this later
  122. on to determine if compression is used on help file.
  123. ****************************************************/
  124.  
  125. void SysLoad(FILE *HelpFile, long FileStart) {
  126.  
  127.    FILEHEADER      FileHdr;
  128.  
  129.    fseek(HelpFile, FileStart, SEEK_SET);
  130.    fread(&FileHdr, sizeof(FileHdr), 1, HelpFile);
  131.    fread(&SysHeader, sizeof(SysHeader), 1, HelpFile);
  132.  
  133. }
  134.  
  135.  
  136. /*************************************************
  137.   Returns a 1 if the bit is set, else 0 returned
  138. **************************************************/
  139.  
  140. int BitSet(BYTE BitMap, int Bit) {
  141.   
  142.    if (BitMap & (1<<Bit)) return 1;
  143.                      else return 0;
  144.  
  145. }
  146.  
  147.  
  148. /*************************************************
  149.   Decides how many bytes to read, depending on the
  150.   number of bits set in the Bitmap
  151. **************************************************/
  152.  
  153. int BytesToRead(BYTE BitMap) {
  154.  
  155. int TempSum, counter;
  156.  
  157.     TempSum = 8;
  158.     for (counter = 0; counter < 8; counter ++)
  159.        TempSum += BitSet(BitMap, counter);
  160.  
  161.     return TempSum;
  162. }
  163.  
  164.  
  165. /*************************************************
  166.   Decompresses the data using Microsoft's LZ77
  167. derivative.
  168. **************************************************/ 
  169.  
  170. WORD Decompress(FILE *HelpFile, WORD CompSize, char *Buffer) {
  171.  
  172. WORD InBytes = 0;        /* How many bytes read in                    */
  173. WORD OutBytes = 0;       /* How many bytes written out                */
  174. BYTE BitMap, Set[16];    /* Bitmap and bytes associated with it       */
  175. int  NumToRead;          /* Number of bytes to read for next group    */
  176. int  counter, Index;     /* Going through next 8-16 codes or chars    */
  177. int  Length, Distance;   /* Code length and distance back in 'window' */
  178. char *CurrPos;           /* Where we are at any given moment          */
  179. char *CodePtr;           /* Pointer to back-up in LZ77 'window'       */
  180.  
  181.  
  182.    CurrPos = Buffer;
  183.  
  184.    /* Go through until we're done */
  185.    while (InBytes < CompSize) {
  186.  
  187.       /* Get BitMap and data following it */
  188.       BitMap = fgetc(HelpFile);
  189.       NumToRead = BytesToRead(BitMap);
  190.  
  191.       /* If we're trying to read more than we've got left, only read what we have left. */
  192.       NumToRead = (CompSize - InBytes) < NumToRead ? CompSize-InBytes : NumToRead;
  193.  
  194.       fread(Set, 1, NumToRead, HelpFile);    
  195.       InBytes += NumToRead + 1;
  196.  
  197.       /* Go through and decode data */
  198.       for (counter = 0, Index = 0; counter < 8; counter++) {
  199.  
  200.          /* It's a code, so decode it and copy the data */
  201.          if (BitSet(BitMap, counter)) {
  202.             Length = ((Set[Index+1] & 0xF0) >> 4) + 3;
  203.             Distance = (256 * (Set[Index+1] & 0x0F)) + Set[Index] + 1;
  204.  
  205.             CodePtr = CurrPos - Distance;
  206.  
  207.             /* Copy data from 'window' */
  208.             while (Length) {
  209.                *CurrPos++ = *CodePtr++;
  210.                OutBytes++;
  211.                Length--;
  212.             } 
  213.  
  214.             Index += 2;
  215.  
  216.          } /* if */
  217.  
  218.          else {
  219.             *CurrPos++ = Set[Index++];
  220.             OutBytes++;
  221.          }
  222.  
  223.       } /* for */
  224.  
  225.    } /* while  */
  226.  
  227.    return OutBytes;
  228.    
  229.  
  230. /***************************************************
  231.   List the WHIFS directory to the screen.
  232. ****************************************************/
  233.  
  234. void ListFiles(FILE *HelpFile) {
  235.  
  236.     DWORD           FileCounter;
  237.     char            FileName[20];
  238.     long            FileOffset;
  239.  
  240.  
  241.     /* Load WHIFS Header and Get first leaf */
  242.     WHIFSGetFirstLeaf(HelpFile);
  243.  
  244.     for (FileCounter = 0;
  245.          FileCounter < WHIFSHeader.TotalWHIFSEntries;
  246.          FileCounter++) {
  247.  
  248.         GetFile(HelpFile, FileCounter, &FileOffset, FileName);
  249.  
  250.         printf("File:%-10s FileOffset:0x%08lX ",FileName, FileOffset);
  251.  
  252.         /* Make it double column */
  253.         if ((FileCounter % 2) != 0) printf("\n");
  254.              else printf("|");
  255.     }
  256.  
  257. }
  258.  
  259.  
  260. /***************************************************
  261.   Performs a Hex/ASCII dump of a WHIFS file.
  262. ****************************************************/
  263.  
  264. void HexDump(FILE *HelpFile, long FileStart) {
  265.  
  266.    FILEHEADER  FileHdr;
  267.    char        Buffer[16];
  268.    long        counter;
  269.    int         BytesToPrint, Index;
  270.  
  271.  
  272.    fseek(HelpFile, FileStart, SEEK_SET);
  273.